home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
tsr25src.arc
/
WATCH.ASM
< prev
Wrap
Assembly Source File
|
1987-06-02
|
14KB
|
413 lines
;WATCH.ASM
;resident routine watches programs going resident
;and keeps a list of changes in interrupt vectors to an internal data structure
; written to use MicroSoft MASM version 4
; written by Kim Kokkonen, TurboPower Software
;
; VERSION 2.2 3/4/87
; First release, version to be consistent with MAPMEM.PAS
; VERSION 2.3 5/1/87
; Sets up a separate stack for the interrupt handlers
; to solve problem first noticed with EMMCACHE and WATCH
; Changes approach - store all vector information in RAM buffers
; No disk access at all by WATCH
; Better check for multiple installation
; Changed to use MASM
; VERSION 2.4 5/17/87
; for consistency with RELEASE
; VERSION 2.5 5/28/87
; save flags in int21 handler
;
Cseg segment public para
assume cs:Cseg, ds:nothing, es:nothing, ss:nothing
org 080H
cmdline label byte ;pointer to command line
org 100H
comentry: jmp init
;******************************************************************************
;resident data section follows
;******************************************************************************
;put the following in the MAP file
public bmesg,origv,prevv,vpos,vchg
;resident data structures not part of COM file
vchg equ 220H ;location of data area (>= offset bmesg)
vrecsize equ 8 ;number of bytes per vector change record
vsize equ 80H*vrecsize ;size of vector change area in bytes
;space for 128 changes of vector here
;vector table buffers
origv equ vchg+vsize ;location of original vector table
veclen equ 400H ;size of vector table in bytes
prevv equ origv+veclen ;location of current vector table
newstackpos equ prevv+veclen ;location of newstack
ssize equ 0080H ;number of bytes in temporary stack
newloc equ newstackpos+ssize ;location for relocated installation code
even
vpos dw 0 ;next position to write in data area
;temporary stack used by interrupt handler
newss dw 0 ;segment of our temporary stack
newsp dw 0 ;initial stack pointer
;information saved about the calling program
oldss dw ? ;stack segment
oldsp dw ? ;stack pointer
curpsp dw ? ;program segment
;id code for a PSP data block
pspid equ 0FFFFH ;id used to indicate a PSP block
;int16H function call for id check
getid equ 'wa' ;function code for int16
chkid equ 'WA' ;returned by int16 getid check
;previous interrupt handlers
kbd_int label dword
old16 dw 2 dup (?) ;old int16 vector
dos_int label dword
old21 dw 2 dup (?) ;old int21 vector
tsr_int label dword
old27 dw 2 dup (?) ;old int27 vector
;***********************************************************************
;interrupt handler for int16
;used only to avoid reinstallation
newint16 proc near
assume ds:nothing
pushf ;save application flags
sti
cmp ax,getid ;see if our id function
jne ex16 ;no, pass on to previous int16
mov ax,chkid ;return id code
popf
iret ;back to caller
ex16: popf
jmp kbd_int ;transfer control to the previous int16
newint16 endp
;***********************************************************************
;interrupt handler for int21
newint21 proc near
assume ds:nothing
pushf ;save flags
cmp ah,31H
jne ex21
call checkvec ;call routine to check vector table
ex21: popf
jmp dos_int ;transfer control to the previous int21 vector
newint21 endp
;***********************************************************************
;interrupt handler for int27
newint27 proc near
assume ds:nothing
call checkvec
ex27: jmp tsr_int ;transfer control to the previous int27 vector
newint27 endp
;***********************************************************************
;procedure checkvec
; compares vectors to previous installation
; stores a new vector buffer
; writes information to wfile
checkvec proc near
assume ds:nothing
;save current stack
mov oldss,ss
mov oldsp,sp
;switch to our stack
cli
mov ss,newss
mov sp,newsp
sti
;store registers
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
;get DS set up as CS
mov ax,cs
mov ds,ax
assume ds:cseg
mov ah,51H ;get current PSP
pushf
call dos_int ;bx returns PSP
call vechdr ;store the PSP segment of the program going resident
call cmpvec ;scan the vector table looking for changes from our buffer
mov di,prevv ;save the new version of the vector table
call savevec
;restore registers
pop es
pop ds
assume ds:nothing
pop di
pop si
pop dx
pop cx
pop bx
pop ax
;restore stack
cli
mov ss,oldss
mov sp,oldsp
sti
ret
checkvec endp
;**************************************************************************
;procedure vechdr
; writes a header to the vector data area for this new TSR
; on entry:
; bx has PSP of the new TSR
;
vechdr proc near
assume ds:cseg
cmp vpos,vsize-vrecsize ;assure room for next record
ja vecex ;ignore if no room
push di
mov di,vpos ;index into vchg array
mov word ptr [di+vchg],pspid ;store id word
mov word ptr [di+vchg+2],bx ;store PSP value
;two words in record left unitialized
add vpos,vrecsize ;move to next data element
pop di
vecex: ret
vechdr endp
;**************************************************************************
;procedure wrchg
; writes information about changed vectors to the data area
; on entry
; ax has changed vector number
; ds points to segment 0
; on exit:
; flags changed
;
wrchg proc near
assume ds:nothing, es:nothing
cmp vpos,vsize-vrecsize ;assure room for next record
ja wrcex
push ax
push si
push di
mov di,vpos ;index into vchg array
mov cs:[di+vchg],ax ;store interrupt vector number
mov si,ax
shl si,1
shl si,1 ;get address of vector
mov ax,[si] ;get offset of vector
mov cs:[di+vchg+2],ax ;store vector offset
mov ax,[si+2] ;get segment
mov cs:[di+vchg+4],ax ;store segment
;one word in record left unused
add vpos,vrecsize ;move to next data element
pop di
pop si
pop ax
wrcex: ret
wrchg endp
;**************************************************************************
;procedure cmpvec
; compares vectors in buffer to those in use
; writes numbers of those different to data area
; on exit:
; ax,si,di destroyed
; flags changed
;
cmpvec proc near
assume ds:nothing, es:nothing
push ds
push es
xor si,si ;source offset 0
mov ds,si ;source address segment 0
mov ax,cs
mov es,ax
xor ax,ax ;vector counter
mov di,prevv ;destination offset
cld ;upward direction
nexvec: cmpsw ;compare offsets
je cmpseg ;compare segments if offsets equal
call wrchg ;write changed vector
cmpsw ;compare next word, ignore result
jmp short vecinc
cmpseg: cmpsw ;compare segments
je vecinc
call wrchg ;write changed vector
vecinc: inc ax ;next vector number
cmp ax,00FFH
jbe nexvec ;continue until 256 vectors checked
pop es
pop ds
ret
cmpvec endp
;**************************************************************************
;procedure savevec
; saves image of interrupt vectors
; on entry:
; di has destination offset
; on exit:
; ax,cx,si,di destroyed
; flags changed
;
savevec proc near
assume ds:nothing, es:nothing
push ds
push es
xor si,si ;offset 0
mov ds,si ;source address segment 0
mov ax,cs
mov es,ax ;destination always in this code segment
mov cx,200H ;512 integers to store
cld ;copy up
rep movsw ;copy vectors to our table
pop es
pop ds
ret
savevec endp ;of proc savevec
;**************************************************************************
;resident portion above, temporary portion below
;**************************************************************************
;temporary strings
even
bmesg db 13,10,'Cannot install WATCH more than once....',13,10,36
mesg db 13,10,'WATCH 2.5 successfully installed',13,10,36
pname db 'TSR WATCHER'
plen equ $-pname ;length of string
;**************************************************************************
;install new handlers for DOS go-resident services
init proc near
assume ds:cseg
;use int 16h test to check for previous installation
mov ax,getid ;int16h diagnostic request
int 16h ;now, ax=chkid if installed
cmp ax,chkid ;TSR already installed?
jne success ;no - jump if not installed
;error exit
mov dx,offset bmesg ;error message
mov ah,09H
int 21H ;DOS print string
mov ax,4C01H ;exit with error
int 21H
;print a success message
success: mov dx,offset mesg ;start of message to write
mov ah,09H
int 21H ;DOS print string
;relocate ourselves out of the way of the vector tables
mov ax,cs
mov es,ax
mov di,newloc+10H
push di ;will act as a return address
mov si,offset newstk
mov cx,lastcode-newstk
rep movsb ;move code
ret ;"return" to the relocated code
;initialize location of WATCH stack
newstk: mov newsp,newstackpos+ssize
mov newss,cs ;stack seg is code seg
;get int 16H vector
mov ax,3516H ;GetVector DOS function call
int 21H
mov old16,bx ;store first word of old21
mov old16[2],es ;store second word
;get int 21H vector
mov ax,3521H ;GetVector DOS function call
int 21H
mov old21,bx ;store first word of old21
mov old21[2],es ;store second word
;get int 27H vector
mov ax,3527H ;GetVector DOS function call
int 21H
mov old27,bx ;store first word of old27 (offset)
mov old27[2],es ;store second word (segment)
;put an id label at offset 80H to allow other programs to recognize WATCH
mov ax,cs
mov es,ax
mov cx,plen ;length of name string
mov si,offset pname ;offset of name string
mov di,offset cmdline ;offset of DOS command line
cld ;transfer in forward direction
mov al,cl
stosb ;store length byte first
rep movsb ;transfer characters
;store image of original vector table (overwrites messages)
mov di,origv
mov ax,offset savevec
call ax ;absolute call works as code is moved
;store it again into the current vector table
mov di,prevv
mov ax,offset savevec
call ax ;absolute call works as code is moved
;install the new vectors
mov ax,2516H
mov dx,offset newint16
int 21H
mov ax,2521H
mov dx,offset newint21
int 21H
mov ax,2527H
mov dx,offset newint27
int 21H
;terminate and stay resident
mov dx,(newloc+15) shr 4
mov ax,3100H ;return success code
int 21H
lastcode:
init endp
Cseg ends
end ComEntry